home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 501-525 / disk_519 / oaklisp / src.lzh / stacks.c < prev    next >
C/C++ Source or Header  |  1991-06-15  |  4KB  |  154 lines

  1. /* Copyright (C) 1987, Barak Pearlmutter & Kevin Lang. */
  2.  
  3. #include <stdio.h>
  4. #include "emulator.h"
  5. #include "stacks.h"
  6.  
  7. #ifndef FAST
  8. extern bool trace_segs;
  9. #endif
  10.  
  11. /* This routine flushes out the stack buffer, leaving amount_to_leave. */
  12. void flush_buffer(pstk, amount_to_leave)
  13.      stack *pstk;
  14.      int amount_to_leave;
  15. {
  16.   segment *s;
  17.   long i , count = pstk->ptr - (&pstk->data[0]-1)
  18.     , amount_to_flush = count - amount_to_leave
  19.       , amount_unflushed = amount_to_flush;
  20.   ref *src = &pstk->data[0]
  21.     , *end = pstk->ptr - amount_to_leave;
  22.   
  23.   while (src < end)
  24.     {
  25.       /* Flush a single segment. */
  26.       long size = amount_unflushed;
  27.  
  28.       if (size > MAX_SEGMENT_SIZE)
  29.     size = MAX_SEGMENT_SIZE;
  30.       
  31.       {
  32.     ref *p;
  33.  
  34.     ALLOCATE(p, size+SEGMENT_HEADER_LENGTH,
  35.          "space crunch allocating stack segment");
  36.  
  37.     s = (segment *)p;
  38.       }
  39.  
  40.       s->type_field = e_segment_type;
  41.       s->length_field = INT_TO_REF(size+SEGMENT_HEADER_LENGTH);
  42.       s->previous_segment = pstk->segment;
  43.       pstk->segment = PTR_TO_REF(s);
  44.  
  45.       for (i=0; i<size; i++)
  46.     s->data[i] = *src++;
  47.  
  48.       amount_unflushed -= size;
  49. #ifndef FAST
  50.       if (trace_segs) printf("P");
  51. #endif
  52.     }
  53.  
  54.   for (i=0; i<amount_to_leave; i++)
  55.     pstk->data[i] = *src++;
  56.  
  57.   pstk->ptr = &pstk->data[amount_to_leave-1];
  58.   pstk->pushed_count += amount_to_flush;
  59. #ifndef FAST
  60.   if (trace_segs) printf(".");
  61. #endif
  62. }
  63.  
  64.  
  65.  
  66. /* This routine grabs some segments that have been flushed from the buffer
  67.    and puts them back in.  Because the segments might be small, it
  68.    may have to put more than one segment back in.  It grabs enough so that
  69.    the buffer has at least n+1 values in it, so that at least n values could
  70.    be popped off without underflow. */
  71.  
  72. void unflush_buffer(pstk, n)
  73.      stack *pstk;
  74.      int n;
  75. {
  76.   long i
  77.     , number_to_pull = 0
  78.     , count = pstk->ptr - (&pstk->data[0]-1)
  79.     , new_count = count;
  80.   segment *s = (segment *)REF_TO_PTR(pstk->segment);
  81.   ref *dest;
  82.  
  83.   /* First, figure out how many segments to pull. */
  84.   for (; new_count <= n; s = (segment *)REF_TO_PTR(s->previous_segment))
  85.     {
  86.       new_count += REF_TO_INT(s->length_field) - SEGMENT_HEADER_LENGTH;
  87.       number_to_pull += 1;
  88.     }
  89.  
  90.   /* Copy the data in the buffer up to its new home. */
  91.   dest = &pstk->data[new_count - 1];
  92.  
  93.   for (i = count-1; i>=0; i--)
  94.     *dest-- = pstk->data[i];
  95.  
  96.   /* Suck in the segments. */
  97.   for (s = (segment *)REF_TO_PTR(pstk->segment);
  98.        number_to_pull>0; number_to_pull--)
  99.     {
  100.       /* Suck in this segment. */
  101.       for (i = REF_TO_INT(s->length_field) - SEGMENT_HEADER_LENGTH - 1
  102.        ; i >= 0; i--)
  103.     *dest-- = s->data[i];
  104.       s = (segment *)REF_TO_PTR(s->previous_segment);
  105. #ifndef FAST
  106.       if (trace_segs) printf("p");
  107. #endif
  108.     }
  109.  
  110.   pstk->segment = PTR_TO_REF(s);
  111.   pstk->ptr = &pstk->data[new_count-1];
  112.   pstk->pushed_count -= new_count - count;
  113. #ifndef FAST
  114.   if (trace_segs) printf(".");
  115. #endif
  116. }
  117.  
  118.       
  119.  
  120.  
  121.  
  122. void dump_stack_proc(pstk)
  123.      stack *pstk;
  124. {
  125.   ref *p;
  126.  
  127.   (void)printf("stack contents (%d): ", stk_height(*pstk));
  128.  
  129.   /* For now, we don't bother to print the segments. */
  130.  
  131.   for (p = &pstk->data[0]; p<=pstk->ptr; p++)
  132.     {
  133.       printref(*p);
  134.       (void)putc(p == pstk->ptr ? '\n' : ' ', stdout);
  135.     }
  136.  
  137.   fflush_stdout();
  138. }
  139.  
  140.  
  141.  
  142. void init_stk(pstk)
  143.      stack *pstk;
  144. {
  145. #ifdef MALLOC_STACK_BUFFER
  146.   pstk->data = (ref *)my_malloc((long)(sizeof(ref) * STACK_BUFFER_SIZE));
  147. #endif
  148.   pstk->ptr = &pstk->data[0];
  149.   pstk->data[0] = INT_TO_REF(1234);
  150.   /* This becomes e_nil when segment_type is loaded. */
  151.   pstk->segment = INT_TO_REF(0);
  152.   pstk->pushed_count = 0;
  153. }
  154.